package com.dh.cheesestrip.HttpUtil;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;

import com.dh.cheesestrip.Config;
import com.dh.cheesestrip.HttpUtil.callback.HttpCallback;
import com.dh.cheesestrip.R;
import com.dh.cheesestrip.Util.DialogUtil;
import com.dh.cheesestrip.Util.LogUtil;
import com.dh.cheesestrip.Util.StringUtil;
import com.dh.cheesestrip.Util.jsonUtil;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by M.c on 2016/1/6.
 */
public class HttpSender {

    private static HttpSender mInstance;
    private Context context;
    private int timeOut = 10000;//单位毫秒
    private String url;
    private String name = "默认接口名称";
    private int id = 0;
    private int httpMode = HttpMode.GET;
    private Object obj = null;
    private boolean isShowDialog = true;
    private OkHttpClient mOkHttpClient;
    private HttpCallback callback;
    private Handler mDelivery;
    private String firstUrlChar = "?";

    public Handler getDelivery() {
        return mDelivery;
    }

    private HttpSender() {
        mOkHttpClient = new OkHttpClient();
        mDelivery = new Handler(Looper.getMainLooper());
    }

    public static HttpSender getInstance() {
        if (mInstance == null) {
            synchronized (HttpSender.class) {
                if (mInstance == null) {
                    mInstance = new HttpSender();
                }
            }
        } else {
            initAllParam();
        }

        return mInstance;
    }

    /**
     * 初始化所有参数
     */
    private static void initAllParam() {
        mInstance.timeOut = 10000;//单位毫秒
        mInstance.url = "";
        mInstance.name = "默认接口名称";
        mInstance.id = 0;
        mInstance.httpMode = HttpMode.GET;
        mInstance.obj = null;
        mInstance.context = null;
        mInstance.isShowDialog = true;
    }

    public HttpSender setCallback(HttpCallback callback) {
        this.callback = callback;
        return this;
    }

    public HttpSender setContext(Context context) {
        this.context = context;
        return this;
    }

    public HttpSender setTimeOut(int timeOut) {
        this.timeOut = timeOut;
        return this;
    }

    public HttpSender setUrl(String url) {
        this.url = url;
        return this;
    }

    public HttpSender setName(String name) {
        this.name = name;
        return this;
    }

    public HttpSender setId(int id) {
        this.id = id;
        return this;
    }

    public HttpSender setHttpMode(int httpMode) {
        this.httpMode = httpMode;
        return this;
    }

    public HttpSender setObj(Object obj) {
        this.obj = obj;
        return this;
    }

    public HttpSender setShowDialog(boolean showDialog) {
        isShowDialog = showDialog;
        return this;
    }

    /**
     * 执行请求
     */
    public void sender() {

        if (StringUtil.isBlank(url)) {
            LogUtil.e(Config.app().getString(R.string.empty_url));
            return;
        }
        Request request = null;
        Map<String, Object> map = null;
        if (null == obj) {
            LogUtil.w(Config.app().getString(R.string.empty_obj));
        } else {
            map = jsonUtil.json2Map(jsonUtil.toJson(obj));
        }

        if (callback == null) {
            callback = HttpCallback.CALLBACK_DEFAULT;
        }
        final HttpCallback finalCallback = callback;


        switch (httpMode) {
            default:
                LogUtil.e(Config.app().getString(R.string.error_http_mode));
                break;
            case HttpMode.GET:
            case HttpMode.FREE:
                StringBuilder urlBuilder = new StringBuilder(url);
                if (null != obj) {
                    urlBuilder.append(firstUrlChar);
                    for (Map.Entry<String, Object> entry : map.entrySet()) {
                        urlBuilder.append(entry.getKey() + "=" + entry.getValue().toString() + "&");
                    }
                    urlBuilder.deleteCharAt(urlBuilder.length() - 1);
                }
                LogUtil.i("请求: " + urlBuilder.toString());
                request = new Request.Builder().url(urlBuilder.toString()).build();

                break;
            case HttpMode.POST:
                if (null != obj) {
                    LogUtil.i("请求: " + url);
                    LogUtil.i("请求对象: " + jsonUtil.format(jsonUtil.toJson(obj)));

                    FormBody.Builder builder = new FormBody.Builder();
                    for (Map.Entry<String, Object> entry : map.entrySet()) {
                        builder.add(entry.getKey(), entry.getValue().toString());
                    }
                    request = new Request.Builder().url(url).post(builder.build()).build();
                } else {
                    LogUtil.i("请求: " + url);
                    request = new Request.Builder().url(url).build();
                }


                break;
            case HttpMode.DOWNLOAD:
                request = new Request.Builder().url(url).build();
                break;
        }

        finalCallback.onBefore();
        if (isShowDialog && null != context && httpMode != HttpMode.DOWNLOAD) {
            DialogUtil.getInstance().showLoadingDialog(context);
        }
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                sendErrorlResultCallback(call.request(), e, finalCallback);
            }


            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String resStr = null;
                if (httpMode != HttpMode.DOWNLOAD) {
                    resStr = response.body().string();
                }


                if (response.code() >= 400 && response.code() <= 599) {
                    sendErrorlResultCallback(response.request(), new RuntimeException(resStr), finalCallback);
                    return;
                }

                switch (httpMode) {
                    default:
                    case HttpMode.GET:
                    case HttpMode.POST:
                        LogUtil.i("服务器返回: " + resStr);
                        try {
                            HttpResObj obj = jsonUtil.json2Bean(resStr, HttpResObj.class);
                            if (obj.getStatus() != 200) {
                                sendFailureResultCallback(obj, finalCallback);
                            } else {
                                Object o = finalCallback.parseNetworkResponse(obj);
                                sendSuccessResultCallback(o, finalCallback);
                            }

                        } catch (IOException e) {
                            e.printStackTrace();
                            sendErrorlResultCallback(response.request(), e, finalCallback);
                        } catch (Exception e) {
                            LogUtil.e("JSON解析错误!");
                            DialogUtil.getInstance().dismissLoadingDialog();
                            e.printStackTrace();
                        }
                        break;

                    case HttpMode.FREE:
                        LogUtil.i("服务器返回: " + resStr);
                        sendSuccessResultCallback(resStr, finalCallback);

                        break;
                    case HttpMode.DOWNLOAD:
                        try {
                            Object o = finalCallback.parseNetworkResponse(response);
                            sendSuccessResultCallback(o, finalCallback);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                        break;
                }


            }
        });
    }


    private void sendErrorlResultCallback(final Request request, final Exception e, final HttpCallback callback) {
        if (callback == null) return;

        mDelivery.post(new Runnable() {
            @Override
            public void run() {
                callback.onError(request, e);
                callback.onAfter();
            }
        });
    }

    private void sendSuccessResultCallback(final Object object, final HttpCallback callback) {
        if (callback == null) return;
        mDelivery.post(new Runnable() {
            @Override
            public void run() {
                callback.onResponse(object);
                callback.onAfter();
            }
        });
    }

    private void sendFailureResultCallback(final HttpResObj object, final HttpCallback callback) {
        if (callback == null) return;
        mDelivery.post(new Runnable() {
            @Override
            public void run() {
                callback.onFailure(object);
                callback.onAfter();
            }
        });
    }

    /**
     * 取消请求
     *
     * @param tag 传入context
     */
    public void cancelTag(Object tag) {
        LogUtil.e("取消请求");
        for (Call call : mOkHttpClient.dispatcher().queuedCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
        for (Call call : mOkHttpClient.dispatcher().runningCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
    }

    /**
     * 设置https证书
     *
     * @param certificates
     */
    public void setCertificates(InputStream... certificates) {
        mOkHttpClient = getOkHttpClient().newBuilder()
                .sslSocketFactory(HttpsUtils.getSslSocketFactory(certificates, null, null))
                .build();
    }

    public OkHttpClient getOkHttpClient() {
        return mOkHttpClient;
    }
}
